package com.mall.bargain.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mall.bargain.fenign.ItemFeignService;
import com.mall.bargain.fenign.ItemSpecFeignService;
import com.mall.bargain.mapper.*;
import com.mall.bargain.service.IBargainService;
import com.mall.bargain.vo.VoBargain;
import com.mall.bargain.vo.VoImages;
import com.mall.bargain.vo.VoTbImage;
import com.mall.common.response.CommonResponse;
import com.mall.constant.enums.CommonStatus;
import com.mall.constant.strings.*;
import com.mall.entity.TbBargain;
import com.mall.entity.TbItem;
import com.mall.entity.TbItmeSpec;
import com.mall.entity.bargain.BgBargain;
import com.mall.entity.bargain.BgBargainItem;
import com.mall.entity.bargain.BgBargainRecord;
import com.mall.entity.bargain.BgUserBargain;
import com.mall.utils.IdWorker;
import io.swagger.models.auth.In;
import org.redisson.Redisson;
import org.redisson.api.RMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: W
 * @date: 2021/07/20/17:31
 * Other: 砍价活动业务层
 */
@Service
@Transactional
public class BargainServiceImpl implements IBargainService {

    @Autowired
    private BargainMapper bargainMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsEvaluateMapper evaluateMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private Redisson redisson;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ItemFeignService itemFeignService;

    @Autowired
    private UserBargainMapper userBargainMapper;

    @Autowired
    private BargainRecordMapper bargainRecordMapper;

    @Autowired
    private BargainItemMapper bargainItemMapper;


    @Autowired
    private ItemSpecFeignService itemSpecFeignService;

    @Override
    public List<BgBargain> findList() {
        //从缓存中获取砍价商品信息
        RMap<Long, BgBargain> map = redisson.getMap(MapMsg.BARGAINLIST_MAP);
        Map<Long, BgBargain> maps = null;
        if (map.size()==0){
            //缓存没有，查数据库
            List<BgBargain> bgBargains = bargainMapper.findList();
            maps = bgBargains.stream().collect(Collectors.toMap(BgBargain::getId, Function.identity(), (key1, key2) -> key2));
            map.putAll(maps);
            return bgBargains;
        }else{
            List<BgBargain> collect = map.entrySet().stream().map(en -> en.getValue()).collect(Collectors.toList());
            collect.stream().forEach(n-> System.out.println(n));
            return collect;
        }
    }

    /**
     * 开始砍价
     *
     * @param uid uid 用户ID
     * @param specItemId  id  具体商品id
     * @return boolean
     */
    @Override
    public CommonResponse startBargain(Integer uid, Long specItemId) {
        boolean flag = true;
        String returnMsg = "";
        // 查询具体砍价商品
        BgBargainItem bargainItem = bargainItemMapper.findOne(specItemId);
        // 查询砍价活动
        BgBargain bargain = bargainMapper.findByItemId(bargainItem.getItemId());
        List<BgUserBargain> userBargainList = userBargainMapper.findByUserIdAndBargainId(uid,bargain.getId());
        if (userBargainList != null) {
            if (userBargainList.size() == bargain.getBuyLimit()) {
                returnMsg = ErrorMsg.MAXIMUM_NUMBER_OF_ACTIVITIES;
                flag = false;
            }
        }// 不在活动范围时间之内
        if (bargainItem.getLimitSurplus() == 0){
            returnMsg = ErrorMsg.ERROR_NUM_404;
            flag = false;
        }if (System.currentTimeMillis() <= bargain.getStartingTime().getTime()
                || System.currentTimeMillis() >= bargain.getEndTime().getTime()) {
            returnMsg =  ErrorMsg.OVER_TIME;
            flag = false;
        }
        if (!flag){
            return new CommonResponse(CommonStatus.UNVALID.getCode(),returnMsg);
        }
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(MapMsg.BARGAIN_LOCK_KEY, "" +
                specItemId,IntStant.Ten, TimeUnit.SECONDS);
        if (!absent) {
            return new CommonResponse(CommonStatus.UNVALID.getCode(), ErrorMsg.SYSTEM_IS_BUSY);
        }else {
            // 点击砍价业务逻辑  首先 限量剩余-1 参与人数+1
            bargainItemMapper.updateLimitSurplus(bargainItem.getSpecItemId(),-1);
            bargain.setLimitSurplus(bargain.getLimitSurplus() - 1);
            // 参与人数 +1
            bargain.setParticipant(bargain.getParticipant()+ 1);
            bargainMapper.UpdateOne(bargain);
            // 用户参与 金刀  97%
            BgUserBargain userBargain = new BgUserBargain();
            userBargain.setUserId(uid);
            userBargain.setSpecItemId(specItemId);
            userBargain.setBargainId(bargain.getId());
            userBargain.setCreateTime(new Date());
            userBargain.setUpdateTime(new Date());
            userBargain.setStatus(ConstantStrings.ZERO);
            userBargain.setFinishRate(97.0);
            BigDecimal yetPrice = new BigDecimal((bargainItem.getPrice().doubleValue() * 0.97));
            userBargain.setYetPrice(yetPrice);
            // 剩余砍价次数
            userBargain.setRemainingCount(bargain.getTotalTimes() - 1);
            userBargainMapper.insert(userBargain);
            stringRedisTemplate.opsForValue().set("bargain_"+userBargain.getId(),"帮忙砍一刀",48,TimeUnit.HOURS);
            // 添加记录
            BgBargainRecord record = new BgBargainRecord();
            record.setCreateTime(new Date());
            record.setUserId(uid);
            record.setUserBargainId(userBargain.getId());
            record.setBargainPrice(yetPrice);
            record.setUpdateTime(new Date());
            bargainRecordMapper.insert(record);
            redisTemplate.delete(MapMsg.BARGAIN_LOCK_KEY);
            return new CommonResponse(CommonStatus.VALID.getCode(), SuccessMsg.SUCCESS_CODE_200,userBargain);
        }
    }

    /**
     * 砍一刀
     * @param uid           帮忙人 uid
     * @param userBargainId 用户交易id
     * @return {@link CommonResponse}
     */
    @Override
    public CommonResponse cutAKnife(Integer uid, Integer userBargainId) {
        boolean flag = true;String returnMsg = "";
        BgUserBargain userBargain = userBargainMapper.findOne(userBargainId);
        String s = stringRedisTemplate.opsForValue().get("bargain_" + userBargainId);
        if (s == null || "".equals(s)) {
            flag = false;
            returnMsg =  SuccessMsg.ACTIVITY_HAS_EXPIRED;
        }if (userBargain.getStatus().equals(ConstantStrings.ONE)){
            flag = false;
            returnMsg =  SuccessMsg.THANKS_FOR_PARTICIPATION;
        }// 查询记录 帮助过无法再次帮助
        BgBargainRecord bargainRecord = bargainRecordMapper.findByUidAndUserBargainId(uid,userBargain.getId());
        if (bargainRecord != null){
            flag = false;
            returnMsg = SuccessMsg.HAVE_BEEN_IN;
        }
        if (!flag){
            return new CommonResponse(CommonStatus.VALID.getCode(),returnMsg);
        }// 开始帮忙砍价
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(MapMsg.BARGAIN_LOCK_ONE, "" + userBargainId,10, TimeUnit.SECONDS);
        if (!absent) {
            return new CommonResponse(CommonStatus.UNVALID.getCode(), ErrorMsg.SYSTEM_IS_BUSY);
        }else {
            // 获取砍价所需金额
            BigDecimal needPrice = (BigDecimal)redisTemplate.opsForValue().get("need_price" + userBargain.getUserId());
            BgBargainItem bargainItem = bargainItemMapper.findOne(userBargain.getSpecItemId());
            BgBargain bargain = bargainMapper.findByItemId(bargainItem.getItemId());
            if (needPrice == null){
                // 获取具体商品
                needPrice = new BigDecimal((bargainItem.getPrice().doubleValue() - bargainItem.getPrice().doubleValue() * 0.97)/(bargain.getTotalTimes()-1)).setScale(2, BigDecimal.ROUND_DOWN);
                redisTemplate.opsForValue().set("need_price"+userBargain.getUserId(),needPrice);
            }
            if (userBargain.getYetPrice().add(needPrice).doubleValue() >= bargainItem.getPrice().doubleValue()) {
                needPrice = new BigDecimal(bargainItem.getPrice().doubleValue() - userBargain.getYetPrice().doubleValue());
                // 完成砍价
                userBargain.setStatus(ConstantStrings.ONE);
                userBargain.setFinishRate(100.0);
                bargain.setSuccessCount(bargain.getSuccessCount()+1);
            }
            userBargain.setYetPrice(userBargain.getYetPrice().add(needPrice));
            userBargain.setFinishRate(userBargain.getYetPrice().doubleValue() / bargainItem.getPrice().doubleValue());
            userBargain.setUpdateTime(new Date());
            userBargain.setRemainingCount(userBargain.getRemainingCount() -1);
            userBargainMapper.update(userBargain);
            bargain.setHelpPeople(bargain.getHelpPeople()+1);
            bargain.setParticipant(bargain.getParticipant()+1);
            bargainMapper.UpdateOne(bargain);
            // 添加记录
            BgBargainRecord record = new BgBargainRecord();
            record.setCreateTime(new Date());
            record.setUserId(uid);
            record.setUserBargainId(userBargainId);
            record.setUpdateTime(new Date());
            record.setBargainPrice(needPrice);
            bargainRecordMapper.insert(record);
            redisTemplate.delete(MapMsg.BARGAIN_LOCK_ONE);
            return new CommonResponse(CommonStatus.VALID.getCode(), SuccessMsg.SUCCESS_CODE_200, record);
        }
    }

    @Override
    public CommonResponse updateStatusById(Long id, String status) {
        bargainMapper.updateStatusByBargainId(id,status);
        return new CommonResponse(CommonStatus.SUCCESS.getCode(), SuccessMsg.SUCCESS_CODE_200);
    }

    @Scheduled(cron = "0 0 0 */1 * ?")
    public void updateBargain(){
        List<BgBargain> bgBargains = bargainMapper.findList();
        bgBargains.stream().forEach(item->{
            if (item.getEndTime().getTime()-System.currentTimeMillis()<0){
                bargainMapper.updateStatusById(item.getId());
            }
        });
        RMap<Long, BgBargain> map = redisson.getMap(MapMsg.BARGAINLIST_MAP);
        map.clear();
    }

    /**
     * @author Administrator
     * 回显商品主图和商品轮播图
     */
    @Override
    public VoTbImage findImage(Long id) {
        //拿着id查询goods表里的image返回到vo实体类
        VoTbImage tbImage = goodsMapper.findImage(id);
        //拿着id查询goods_carousel表里的轮播图并返回list集合
        List<VoImages> images = evaluateMapper.findImage(id);
        tbImage.setImages(images);
        return tbImage;
    }

    /**
     * @author Administrator
     * 添加砍价商品
     */
    @Override
    public void addBargain(VoBargain bargain) {

        Integer count = 0;
        // 商品多规格
        if (bargain.getBargainItemList().size() >= 1) {
            for (BgBargainItem bargainItem : bargain.getBargainItemList()) {
                bargainItem.setSpecItemId(bargainItem.getId());
                TbItem item = itemFeignService.findByGoodsId(bargainItem.getGoodsId());
                bargainItem.setItemId(item.getId());
                bargainItem.setLimitSurplus(bargainItem.getLimitNum());
                bargainItemMapper.add(bargainItem);
                // 减少库存
                TbItmeSpec itemSpec = itemSpecFeignService.findById(bargainItem.getSpecItemId());
                itemSpec.setInventory(itemSpec.getInventory() - bargainItem.getLimitNum());
                itemSpecFeignService.update(itemSpec);
                count += bargainItem.getLimitNum();
                item.setInventory(item.getInventory() - bargainItem.getLimitNum());
                itemFeignService.update(item);
            }

            bargain.setLimitNum(count);
        } else {
            // 单规格商品
            BgBargainItem bargainItem = new BgBargainItem();
            bargainItem.setSpecItemId(bargainItem.getItemId());
            bargainItem.setItemId(bargain.getItemId());
            bargainItem.setPrice(bargain.getPrice());
            bargainItem.setLimitNum(bargain.getLimitNum());
            bargainItem.setLimitSurplus(bargain.getLimitNum());
            bargainItemMapper.add(bargainItem);
            TbItem one = itemFeignService.findOne(bargainItem.getItemId());
            one.setInventory(one.getInventory() - bargainItem.getLimitNum());
            itemFeignService.update(one);
        }
        bargain.setId(idWorker.nextId());
        // 限量剩余
        bargain.setLimitSurplus(bargain.getLimitNum());
        bargain.setHelpPeople(0);
        bargain.setParticipant(0);
        bargain.setSuccessCount(0);
        bargainMapper.addBargain(bargain);
    }

    /**
     * @author Administrator
     * 查询砍价商品
     */
    @Override
    public PageInfo findBargainAll(VoBargain bargain, int page, int size) {
        PageHelper.startPage(page, size);
        List<VoBargain> bargainAll = bargainMapper.findBargainAll(bargain);
        return new PageInfo(bargainAll);
    }

    /**
     * @author Administrator
     * 查询砍价商品
     */
    @Override
    public void updateBargainById(TbBargain bargain) {
        bargainMapper.updateBargainById(bargain);
    }

    /**
     * @author Administrator
     * 回显砍价商品
     */
    @Override
    public TbBargain findBargainOne(Long id) {
        return bargainMapper.findBargainOne(id);
    }

    @Override
    public void delBargainOne(Integer id) {
        bargainMapper.delBargainOne(id);
    }

    @Override
    public List<TbItmeSpec> findItemSpecAll(Long goodsId) {
        return bargainMapper.findItemSpecAll(goodsId);
    }
}
